Skip to content

feat: add WASI Preview 1 stubs for wasip1-targeting languages#4641

Open
djgilcrease wants to merge 2 commits intoclockworklabs:masterfrom
digitalxero:wasm-shim
Open

feat: add WASI Preview 1 stubs for wasip1-targeting languages#4641
djgilcrease wants to merge 2 commits intoclockworklabs:masterfrom
digitalxero:wasm-shim

Conversation

@djgilcrease
Copy link

@djgilcrease djgilcrease commented Mar 14, 2026

Description of Changes

Summary

Add minimal WASI Preview 1 stub implementations so that modules compiled to wasip1 (e.g. Go with -buildmode=c-shared) can be instantiated and run in SpacetimeDB's wasmtime
runtime.

  • Add wasi_stubs.rs with stub implementations for wasi_snapshot_preview1 imports (fd_write, clock_time_get, random_get, proc_exit, args_sizes_get, environ_sizes_get,
    sched_yield, etc.)
  • Link the stubs into the wasmtime linker during module setup
  • Call _initialize/_start exports (WASI reactor/command convention) before preinit functions to initialize the guest language runtime

Why

Languages like Go use //go:wasmimport for WASI functions, which must be satisfied by the host. Without these stubs, wasmtime fails to instantiate wasip1-targeting modules because
the wasi_snapshot_preview1 imports are unresolved. The C++ SDK handles this differently by embedding shims in the compiled module itself
(crates/bindings-cpp/src/abi/wasi_shims.cpp), but Go (and potentially other languages) require host-side stubs.

This is a prerequisite for the Go server SDK but is language-agnostic — any wasip1-targeting language benefits from these stubs.

This can also replace the stubs that were added separately for C # and C++, so those and Go can all share the same stubs. I did not update the C# and cpp modules to use these stubs in this MR as I want it to be as minimal as possible so I could start using my go server module asap.

What the stubs do

Function Behavior
fd_write Redirects stdout/stderr to host logger (log::info! / log::warn!)
clock_time_get Returns real wall-clock time (Go panics on zero)
random_get Fills buffer with pseudo-random bytes
args_sizes_get / args_get Returns argc=0, no args
environ_sizes_get / environ_get Returns no environment variables
poll_oneoff Reports all subscriptions as ready
proc_exit / sched_yield No-op
fd_close / fd_seek / fd_read / fd_fdstat_get / fd_fdstat_set_flags / fd_prestat_get / fd_prestat_dir_name Returns ERRNO_BADF or ERRNO_NOSYS

Impact on existing modules

None. These changes are purely additive:

  • The WASI stubs only add new linker functions in the wasi_snapshot_preview1 namespace, which existing Rust/C# modules don't import
  • The _initialize/_start detection is a no-op for modules that don't export them

API and ABI breaking changes

None

Expected complexity level and risk

1 - very low complexity and risk, the stubs are not used by anything, BUT will enable me to externalize a go-sdk for server modules

Testing

ran the full test suite locally

Add minimal WASI function stubs (fd_write, clock_time_get, random_get,
etc.) so that modules compiled to `wasip1` (e.g. Go with
`-buildmode=c-shared`) can run in SpacetimeDB's wasmtime runtime.

This includes:
- wasi_stubs.rs: stub implementations for wasi_snapshot_preview1 imports
- Linking the stubs into the wasmtime linker
- Calling `_initialize`/`_start` exports before other module exports
  to initialize the language runtime (WASI reactor/command convention)

These changes are additive — existing Rust/C# modules are unaffected
since they don't import WASI functions or export `_initialize`/`_start`.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant